Backbone.Collection.extend.fetch   F
last analyzed

Complexity

Conditions 16
Paths 5760

Size

Total Lines 102

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 16
c 2
b 0
f 0
nc 5760
nop 1
dl 0
loc 102
rs 2

2 Functions

Rating   Name   Duplication   Size   Complexity  
B 0 6 5
A 0 21 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like Backbone.Collection.extend.fetch often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
  backbone.paginator
3
  http://github.com/backbone-paginator/backbone.paginator
4
5
  Copyright (c) 2016 Jimmy Yuen Ho Wong and contributors
6
7
  @module
8
  @license MIT
9
*/
10
11
import _ from 'underscore';
0 ignored issues
show
introduced by
Definition for rule 'keyword-spacing' was not found
Loading history...
12
import Backbone from 'backbone';
13
14
/**
15
   __BROWSER ONLY__
16
17
   If you already have an object named `PageableCollection` attached to the
18
   `Backbone` module, you can use this to return a local reference to this
19
   PageableCollection class and reset the name PageableCollection to its
20
   previous definition.
21
22
       // The left hand side gives you a reference to this
23
       // PageableCollection implementation, the right hand side
24
       // resets PageableCollection to your other PageableCollection.
25
       var PageableCollection = PageableCollection.noConflict();
26
27
   @static
28
   @return {PageableCollection}
29
*/
30
31
"use strict";
0 ignored issues
show
introduced by
Expected an assignment or function call and instead saw an expression.
Loading history...
32
33
var _extend = _.extend;
34
var _omit = _.omit;
35
var _clone = _.clone;
36
var _each = _.each;
37
var _pick = _.pick;
38
var _contains = _.contains;
39
var _isEmpty = _.isEmpty;
40
var _pairs = _.pairs;
41
var _invert = _.invert;
42
var _isArray = _.isArray;
43
var _isFunction = _.isFunction;
44
var _isObject = _.isObject;
45
var _keys = _.keys;
46
var _isUndefined = _.isUndefined;
47
var ceil = Math.ceil;
48
var floor = Math.floor;
49
var max = Math.max;
50
51
var BBColProto = Backbone.Collection.prototype;
52
53
function finiteInt(val, name) {
54
  if (!_.isNumber(val) || _.isNaN(val) || !_.isFinite(val) || ~~val !== val) {
0 ignored issues
show
introduced by
Unexpected use of '~'.
Loading history...
55
    throw new TypeError("`" + name + "` must be a finite integer");
56
  }
57
  return val;
58
}
59
60
function queryStringToParams(qs) {
61
  var kvp, k, v, ls, params = {},
62
    decode = decodeURIComponent;
0 ignored issues
show
Bug introduced by
The variable decodeURIComponent seems to be never declared. If this is a global, consider adding a /** global: decodeURIComponent */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
63
  var kvps = qs.split('&');
64
  for (var i = 0, l = kvps.length; i < l; i++) {
65
    var param = kvps[i];
66
    kvp = param.split('='), k = kvp[0], v = kvp[1];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
introduced by
Expected an assignment or function call and instead saw an expression.
Loading history...
introduced by
Unexpected use of comma operator.
Loading history...
67
    if (v == null) v = true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
68
    k = decode(k), v = decode(v), ls = params[k];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
introduced by
Expected an assignment or function call and instead saw an expression.
Loading history...
introduced by
Unexpected use of comma operator.
Loading history...
69
    if (_isArray(ls)) ls.push(v);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
70
    else if (ls) params[k] = [ls, v];
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
71
    else params[k] = v;
0 ignored issues
show
introduced by
Expected { after 'else'.
Loading history...
72
  }
73
  return params;
74
}
75
76
// hack to make sure the whatever event handlers for this event is run
77
// before func is, and the event handlers that func will trigger.
78
function runOnceAtLastHandler(col, event, func) {
79
  var eventHandlers = col._events[event];
80
  if (eventHandlers && eventHandlers.length) {
81
    var lastHandler = eventHandlers[eventHandlers.length - 1];
82
    var oldCallback = lastHandler.callback;
83
    lastHandler.callback = function () {
84
      try {
85
        oldCallback.apply(this, arguments);
86
        func();
87
      } catch (e) {
88
        throw e;
89
      } finally {
90
        lastHandler.callback = oldCallback;
91
      }
92
    };
93
  } else func();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'else'.
Loading history...
94
}
95
96
var PARAM_TRIM_RE = /[\s'"]/g;
97
var URL_TRIM_RE = /[<>\s'"]/g;
98
99
/**
100
 * State change event. Fired when PageableCollection#state gets updated
101
 *
102
 * @event pageable:state:change
103
 * @type {object} The PageableCollection#state object of this
104
 * PageableCollection instance
105
 */
106
107
/**
108
   Drop-in replacement for Backbone.Collection. Supports server-side and
109
   client-side pagination and sorting. Client-side mode also support fully
110
   multi-directional synchronization of changes between pages.
111
112
   @class PageableCollection
113
   @extends Backbone.Collection
114
*/
115
var PageableCollection = Backbone.Collection.extend({
116
117
  /**
118
     The container object to store all pagination states.
119
120
     You can override the default state by extending this class or specifying
121
     them in an `options` hash to the constructor.
122
123
     @property {number} firstPage = 1 - The first page index. Set to 0 if
124
     your server API uses 0-based indices. You should only override this value
125
     during extension, initialization or reset by the server after
126
     fetching. This value should be read only at other times.
127
128
     @property {number} lastPage = null - The last page index. This value
129
     is __read only__ and it's calculated based on whether `firstPage` is 0 or
130
     1, during bootstrapping, fetching and resetting. Please don't change this
131
     value under any circumstances.
132
133
     @property {number} currentPage = null - The current page index. You
134
     should only override this value during extension, initialization or reset
135
     by the server after fetching. This value should be read only at other
136
     times. Can be a 0-based or 1-based index, depending on whether
137
     `firstPage` is 0 or 1. If left as default, it will be set to `firstPage`
138
     on initialization.
139
140
     @property {number} pageSize = 25 - How many records to show per
141
     page. This value is __read only__ after initialization, if you want to
142
     change the page size after initialization, you must call
143
     PageableCollection#setPageSize.
144
145
     @property {number} totalPages = null - How many pages there are. This
146
     value is __read only__ and it is calculated from `totalRecords`.
147
148
     @property {number} totalRecords = null - How many records there
149
     are. This value is __required__ under server mode. This value is optional
150
     for client mode as the number will be the same as the number of models
151
     during bootstrapping and during fetching, either supplied by the server
152
     in the metadata, or calculated from the size of the response.
153
154
     @property {string} sortKey = null - The model attribute to use for
155
     sorting.
156
157
     @property {number} order = -1 - The order to use for sorting. Specify
158
     -1 for ascending order or 1 for descending order. If 0, no client side
159
     sorting will be done and the order query parameter will not be sent to
160
     the server during a fetch.
161
  */
162
  state: {
163
    firstPage: 1,
164
    lastPage: null,
165
    currentPage: null,
166
    pageSize: 25,
167
    totalPages: null,
168
    totalRecords: null,
169
    sortKey: null,
170
    order: -1
171
  },
172
173
  /**
174
     @property {string} mode = "server" The mode of operations for this
175
     collection. `"server"` paginates on the server-side, `"client"` paginates
176
     on the client-side and `"infinite"` paginates on the server-side for APIs
177
     that do not support `totalRecords`.
178
  */
179
  mode: "server",
180
181
  /**
182
     A translation map to convert PageableCollection state attributes
183
     to the query parameters accepted by your server API.
184
185
     You can override the default state by extending this class or specifying
186
     them in `options.queryParams` object hash to the constructor.
187
188
     @property {string} currentPage = "page"
189
     @property {string} pageSize = "per_page"
190
     @property {string} totalPages = "total_pages"
191
     @property {string} totalRecords = "total_entries"
192
     @property {string} sortKey = "sort_by"
193
     @property {string} order = "order"
194
     @property {string} directions = {"-1": "asc", "1": "desc"} - A map for
195
     translating a PageableCollection#state.order constant to the ones your
196
     server API accepts.
197
  */
198
  queryParams: {
199
    currentPage: "page",
200
    pageSize: "per_page",
201
    totalPages: "total_pages",
202
    totalRecords: "total_entries",
203
    sortKey: "sort_by",
204
    order: "order",
205
    directions: {
206
      "-1": "asc",
207
      "1": "desc"
208
    }
209
  },
210
211
  /**
212
     Given a list of models or model attributues, bootstraps the full
213
     collection in client mode or infinite mode, or just the page you want in
214
     server mode.
215
216
     If you want to initialize a collection to a different state than the
217
     default, you can specify them in `options.state`. Any state parameters
218
     supplied will be merged with the default. If you want to change the
219
     default mapping from PageableCollection#state keys to your server API's
220
     query parameter names, you can specifiy an object hash in
221
     `option.queryParams`. Likewise, any mapping provided will be merged with
222
     the default. Lastly, all Backbone.Collection constructor options are also
223
     accepted.
224
225
     See:
226
227
     - PageableCollection#state
228
     - PageableCollection#queryParams
229
     - [Backbone.Collection#initialize](http://backbonejs.org/#Collection-constructor)
230
231
     @constructor
232
233
     @property {Backbone.Collection} fullCollection - __CLIENT MODE ONLY__
234
     This collection is the internal storage for the bootstrapped or fetched
235
     models. You can use this if you want to operate on all the pages.
236
237
     @param {Array.<Object>} models
238
239
     @param {Object} options
240
241
     @param {function(*, *): number} options.comparator - If specified, this
242
     comparator is set to the current page under server mode, or the
243
     PageableCollection#fullCollection otherwise.
244
245
     @param {boolean} options.full 0 If `false` and either a
246
     `options.comparator` or `sortKey` is defined, the comparator is attached
247
     to the current page. Default is `true` under client or infinite mode and
248
     the comparator will be attached to the PageableCollection#fullCollection.
249
250
     @param {Object} options.state - The state attributes overriding the defaults.
251
252
     @param {string} options.state.sortKey - The model attribute to use for
253
     sorting. If specified instead of `options.comparator`, a comparator will
254
     be automatically created using this value, and optionally a sorting order
255
     specified in `options.state.order`. The comparator is then attached to
256
     the new collection instance.
257
258
     @param {number} options.state.order - The order to use for sorting. Specify
259
     -1 for ascending order and 1 for descending order.
260
261
     @param {Object} options.queryParam
262
  */
263
  constructor: function (models, options) {
264
265
    BBColProto.constructor.apply(this, arguments);
266
267
    options = options || {};
268
269
    var mode = this.mode = options.mode || this.mode || PageableProto.mode;
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
270
271
    var queryParams = _extend({}, PageableProto.queryParams, this.queryParams,
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
272
      options.queryParams || {});
273
274
    queryParams.directions = _extend({},
275
      PageableProto.queryParams.directions,
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
276
      this.queryParams.directions,
277
      queryParams.directions);
278
279
    this.queryParams = queryParams;
280
281
    var state = this.state = _extend({}, PageableProto.state, this.state,
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
282
      options.state);
283
284
    state.currentPage = state.currentPage == null ?
0 ignored issues
show
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
285
      state.firstPage :
286
      state.currentPage;
287
288
    if (!_isArray(models)) models = models ? [models] : [];
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
289
    models = models.slice();
290
291
    if (mode != "server" && state.totalRecords == null && !_isEmpty(models)) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
292
      state.totalRecords = models.length;
293
    }
294
295
    this.switchMode(mode, _extend({
296
      fetch: false,
297
      resetState: false,
298
      models: models
299
    }, options));
300
301
    var comparator = options.comparator;
302
303
    if (state.sortKey && !comparator) {
304
      this.setSorting(state.sortKey, state.order, options);
305
    }
306
307
    if (mode != "server") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
308
      var fullCollection = this.fullCollection;
309
310
      if (comparator && options.full) {
311
        this.comparator = null;
312
        fullCollection.comparator = comparator;
313
      }
314
315
      if (options.full) fullCollection.sort();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
316
317
      // make sure the models in the current page and full collection have the
318
      // same references
319
      if (!_isEmpty(models)) {
320
        this.reset(models, _extend({
321
          silent: true
322
        }, options));
323
        this.getPage(state.currentPage);
324
        models.splice.apply(models, [0, models.length].concat(this.models));
325
      }
326
    }
327
328
    this._initState = _clone(this.state);
329
  },
330
331
  /**
332
     Makes a Backbone.Collection that contains all the pages.
333
334
     @private
335
     @param {Array.<Object|Backbone.Model>} models
336
     @param {Object} options Options for Backbone.Collection constructor.
337
     @return {Backbone.Collection}
338
  */
339
  _makeFullCollection: function (models, options) {
340
341
    var properties = ["url", "model", "sync", "comparator"];
342
    var thisProto = this.constructor.prototype;
343
    var i, length, prop;
344
345
    var proto = {};
346
    for (i = 0, length = properties.length; i < length; i++) {
347
      prop = properties[i];
348
      if (!_isUndefined(thisProto[prop])) {
349
        proto[prop] = thisProto[prop];
350
      }
351
    }
352
353
    var fullCollection = new(Backbone.Collection.extend(proto))(models, options);
0 ignored issues
show
introduced by
Unary word operator "new" must be followed by whitespace.
Loading history...
354
355
    for (i = 0, length = properties.length; i < length; i++) {
356
      prop = properties[i];
357
      if (this[prop] !== thisProto[prop]) {
358
        fullCollection[prop] = this[prop];
359
      }
360
    }
361
362
    return fullCollection;
363
  },
364
365
  /**
366
     Factory method that returns a Backbone event handler that responses to
367
     the `add`, `remove`, `reset`, and the `sort` events. The returned event
368
     handler will synchronize the current page collection and the full
369
     collection's models.
370
371
     @private
372
373
     @fires PageableCollection#pageable:state:change when handling an
374
     `add`, `remove`, or `reset` event
375
376
     @param {PageableCollection} pageCol
377
     @param {Backbone.Collection} fullCol
378
379
     @return {function(string, Backbone.Model, Backbone.Collection, Object)}
380
     Collection event handler
381
  */
382
  _makeCollectionEventHandler: function (pageCol, fullCol) {
383
384
    return function collectionEventHandler(event, model, collection, options) {
385
386
      var handlers = pageCol._handlers;
387
      _each(_keys(handlers), function (event) {
0 ignored issues
show
introduced by
"event" is already declared in the upper scope.
Loading history...
388
        var handler = handlers[event];
389
        pageCol.off(event, handler);
390
        fullCol.off(event, handler);
391
      });
392
393
      var state = _clone(pageCol.state);
394
      var firstPage = state.firstPage;
395
      var currentPage = firstPage === 0 ?
396
        state.currentPage :
397
        state.currentPage - 1;
398
      var pageSize = state.pageSize;
399
      var pageStart = currentPage * pageSize,
400
        pageEnd = pageStart + pageSize;
401
402
      if (event == "add") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
403
        var pageIndex, fullIndex, addAt, colToAdd, options = options || {};
0 ignored issues
show
introduced by
"options" is already defined
Loading history...
404
        if (collection == fullCol) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
405
          fullIndex = fullCol.indexOf(model);
406
          if (fullIndex >= pageStart && fullIndex < pageEnd) {
407
            colToAdd = pageCol;
408
            pageIndex = addAt = fullIndex - pageStart;
409
          }
410
        } else {
411
          pageIndex = pageCol.indexOf(model);
412
          fullIndex = pageStart + pageIndex;
413
          colToAdd = fullCol;
414
          var addAt = !_isUndefined(options.at) ?
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable addAt already seems to be declared on line 403. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
introduced by
"addAt" is already defined
Loading history...
415
            options.at + pageStart :
416
            fullIndex;
417
        }
418
419
        if (!options.onRemove) {
420
          ++state.totalRecords;
421
          delete options.onRemove;
422
        }
423
424
        pageCol.state = pageCol._checkState(state);
425
426
        if (colToAdd) {
427
          colToAdd.add(model, _extend({}, options, {
428
            at: addAt
0 ignored issues
show
Bug introduced by
The variable addAt does not seem to be initialized in case fullIndex >= pageStart && fullIndex < pageEnd on line 406 is false. Are you sure this can never be the case?
Loading history...
429
          }));
430
          var modelToRemove = pageIndex >= pageSize ?
0 ignored issues
show
Bug introduced by
The variable pageIndex does not seem to be initialized in case fullIndex >= pageStart && fullIndex < pageEnd on line 406 is false. Are you sure this can never be the case?
Loading history...
introduced by
Do not nest ternary expressions
Loading history...
431
            model :
432
            !_isUndefined(options.at) && addAt < pageEnd && pageCol.length > pageSize ?
433
            pageCol.at(pageSize) :
434
            null;
435
          if (modelToRemove) {
436
            runOnceAtLastHandler(collection, event, function () {
437
              pageCol.remove(modelToRemove, {
438
                onAdd: true
439
              });
440
            });
441
          }
442
        }
443
444
        if (!options.silent) pageCol.trigger("pageable:state:change", pageCol.state);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
445
      }
446
447
      // remove the model from the other collection as well
448
      if (event == "remove") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
449
        if (!options.onAdd) {
450
          // decrement totalRecords and update totalPages and lastPage
451
          if (!--state.totalRecords) {
452
            state.totalRecords = null;
453
            state.totalPages = null;
454
          } else {
455
            var totalPages = state.totalPages = ceil(state.totalRecords / pageSize);
456
            state.lastPage = firstPage === 0 ? totalPages - 1 : totalPages || firstPage;
457
            if (state.currentPage > totalPages) state.currentPage = state.lastPage;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Blocks are nested too deeply (4).
Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
458
          }
459
          pageCol.state = pageCol._checkState(state);
460
461
          var nextModel, removedIndex = options.index;
462
          if (collection == pageCol) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
463
            if (nextModel = fullCol.at(pageEnd)) {
0 ignored issues
show
introduced by
Blocks are nested too deeply (4).
Loading history...
introduced by
Expected a conditional expression and instead saw an assignment.
Loading history...
464
              runOnceAtLastHandler(pageCol, event, function () {
465
                pageCol.push(nextModel, {
466
                  onRemove: true
467
                });
468
              });
469
            } else if (!pageCol.length && state.totalRecords) {
470
              pageCol.reset(fullCol.models.slice(pageStart - pageSize, pageEnd - pageSize),
471
                _extend({}, options, {
472
                  parse: false
473
                }));
474
            }
475
            fullCol.remove(model);
476
          } else if (removedIndex >= pageStart && removedIndex < pageEnd) {
477
            if (nextModel = fullCol.at(pageEnd - 1)) {
0 ignored issues
show
introduced by
Expected a conditional expression and instead saw an assignment.
Loading history...
478
              runOnceAtLastHandler(pageCol, event, function () {
479
                pageCol.push(nextModel, {
480
                  onRemove: true
481
                });
482
              });
483
            }
484
            pageCol.remove(model);
485
            if (!pageCol.length && state.totalRecords) {
486
              pageCol.reset(fullCol.models.slice(pageStart - pageSize, pageEnd - pageSize),
487
                _extend({}, options, {
488
                  parse: false
489
                }));
490
            }
491
          }
492
        } else delete options.onAdd;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'else'.
Loading history...
493
494
        if (!options.silent) pageCol.trigger("pageable:state:change", pageCol.state);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
495
      }
496
497
      if (event == "reset") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
498
        options = collection;
499
        collection = model;
500
501
        // Reset that's not a result of getPage
502
        if (collection == pageCol && options.from == null &&
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
503
          options.to == null) {
0 ignored issues
show
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
504
          var head = fullCol.models.slice(0, pageStart);
505
          var tail = fullCol.models.slice(pageStart + pageCol.models.length);
506
          fullCol.reset(head.concat(pageCol.models).concat(tail), options);
507
        } else if (collection == fullCol) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
508
          if (!(state.totalRecords = fullCol.models.length)) {
509
            state.totalRecords = null;
510
            state.totalPages = null;
511
          }
512
          if (pageCol.mode == "client") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
513
            firstPage = state.lastPage = state.currentPage = state.firstPage;
514
            currentPage = firstPage === 0 ? state.currentPage : state.currentPage - 1;
515
            pageStart = currentPage * pageSize;
516
            pageEnd = pageStart + pageSize;
517
          }
518
          pageCol.state = pageCol._checkState(state);
519
          pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
520
            _extend({}, options, {
521
              parse: false
522
            }));
523
        }
524
525
        if (!options.silent) pageCol.trigger("pageable:state:change", pageCol.state);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
526
      }
527
528
      if (event == "sort") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
529
        options = collection;
530
        collection = model;
531
        if (collection === fullCol) {
532
          pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
533
            _extend({}, options, {
534
              parse: false
535
            }));
536
        }
537
      }
538
539
      _each(_keys(handlers), function (event) {
0 ignored issues
show
introduced by
"event" is already declared in the upper scope.
Loading history...
540
        var handler = handlers[event];
541
        _each([pageCol, fullCol], function (col) {
542
          col.on(event, handler);
543
          var callbacks = col._events[event] || [];
544
          callbacks.unshift(callbacks.pop());
545
        });
546
      });
547
    };
548
  },
549
550
  /**
551
     Sanity check this collection's pagination states. Only perform checks
552
     when all the required pagination state values are defined and not null.
553
     If `totalPages` is undefined or null, it is set to `totalRecords` /
554
     `pageSize`. `lastPage` is set according to whether `firstPage` is 0 or 1
555
     when no error occurs.
556
557
     @private
558
559
     @throws {TypeError} If `totalRecords`, `pageSize`, `currentPage` or
560
     `firstPage` is not a finite integer.
561
562
     @throws {RangeError} If `pageSize`, `currentPage` or `firstPage` is out
563
     of bounds.
564
565
     @return {Object} Returns the `state` object if no error was found.
566
  */
567
  _checkState: function (state) {
568
    var mode = this.mode;
569
    var links = this.links;
570
    var totalRecords = state.totalRecords;
571
    var pageSize = state.pageSize;
572
    var currentPage = state.currentPage;
573
    var firstPage = state.firstPage;
574
    var totalPages = state.totalPages;
575
576
    if (totalRecords != null && pageSize != null && currentPage != null &&
0 ignored issues
show
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
577
      firstPage != null && (mode == "infinite" ? links : true)) {
0 ignored issues
show
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
578
579
      totalRecords = finiteInt(totalRecords, "totalRecords");
580
      pageSize = finiteInt(pageSize, "pageSize");
581
      currentPage = finiteInt(currentPage, "currentPage");
582
      firstPage = finiteInt(firstPage, "firstPage");
583
584
      if (pageSize < 1) {
585
        throw new RangeError("`pageSize` must be >= 1");
586
      }
587
588
      totalPages = state.totalPages = ceil(totalRecords / pageSize);
589
590
      if (firstPage < 0 || firstPage > 1) {
591
        throw new RangeError("`firstPage must be 0 or 1`");
592
      }
593
594
      state.lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages || firstPage;
595
596
      if (mode == "infinite") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
597
        if (!links[currentPage + '']) {
598
          throw new RangeError("No link found for page " + currentPage);
599
        }
600
      } else if (currentPage < firstPage ||
601
        (totalPages > 0 &&
602
          (firstPage ? currentPage > totalPages : currentPage >= totalPages))) {
603
        throw new RangeError("`currentPage` must be firstPage <= currentPage " +
604
          (firstPage ? "<" : "<=") +
605
          " totalPages if " + firstPage + "-based. Got " +
606
          currentPage + '.');
607
      }
608
    }
609
610
    return state;
611
  },
612
613
  /**
614
     Change the page size of this collection.
615
616
     Under most if not all circumstances, you should call this method to
617
     change the page size of a pageable collection because it will keep the
618
     pagination state sane. By default, the method will recalculate the
619
     current page number to one that will retain the current page's models
620
     when increasing the page size. When decreasing the page size, this method
621
     will retain the last models to the current page that will fit into the
622
     smaller page size.
623
624
     If `options.first` is true, changing the page size will also reset the
625
     current page back to the first page instead of trying to be smart.
626
627
     For server mode operations, changing the page size will trigger a
628
     PageableCollection#fetch and subsequently a `reset` event.
629
630
     For client mode operations, changing the page size will `reset` the
631
     current page by recalculating the current page boundary on the client
632
     side.
633
634
     If `options.fetch` is true, a fetch can be forced if the collection is in
635
     client mode.
636
637
     @param {number} pageSize - The new page size to set to PageableCollection#state.
638
     @param {Object} options - {@link PageableCollection#fetch} options.
639
     @param {boolean} options.first = false 0 Reset the current page number to
640
     the first page if `true`.
641
     @param {boolean} options.fetch - If `true`, force a fetch in client mode.
642
643
     @throws {TypeError} If `pageSize` is not a finite integer.
644
     @throws {RangeError} If `pageSize` is less than 1.
645
646
     @chainable
647
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
648
     from fetch or this.
649
  */
650
  setPageSize: function (pageSize, options) {
651
    pageSize = finiteInt(pageSize, "pageSize");
652
653
    options = options || {
654
      first: false
655
    };
656
657
    var state = this.state;
658
    var totalPages = ceil(state.totalRecords / pageSize);
659
    var currentPage = totalPages ?
660
      max(state.firstPage, floor(totalPages * state.currentPage / state.totalPages)) :
661
      state.firstPage;
662
663
    state = this.state = this._checkState(_extend({}, state, {
664
      pageSize: pageSize,
665
      currentPage: options.first ? state.firstPage : currentPage,
666
      totalPages: totalPages
667
    }));
668
669
    return this.getPage(state.currentPage, _omit(options, ["first"]));
670
  },
671
672
  /**
673
     Switching between client, server and infinite mode.
674
675
     If switching from client to server mode, the #fullCollection is emptied
676
     first and then deleted and a fetch is immediately issued for the current
677
     page from the server. Pass `false` to `options.fetch` to skip fetching.
678
679
     If switching to infinite mode, and if `options.models` is given for an
680
     array of models,PageableCollection#links will be populated with a URL per
681
     page, using the default URL for this collection.
682
683
     If switching from server to client mode, all of the pages are immediately
684
     refetched. If you have too many pages, you can pass `false` to
685
     `options.fetch` to skip fetching.
686
687
     If switching to any mode from infinite mode, thePageableCollection#links
688
     will be deleted.
689
690
     @fires PageableCollection#pageable:state:change
691
692
     @param {"server"|"client"|"infinite"} mode - The mode to switch to.
693
694
     @param {Object} options
695
696
     @param {boolean} options.fetch = true - If `false`, no fetching is done.
697
698
     @param {boolean} options.resetState = true - If 'false', the state is not
699
     reset, but checked for sanity instead.
700
701
     @chainable
702
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
703
     from fetch or this if `options.fetch` is `false`.
704
  */
705
  switchMode: function (mode, options) {
706
707
    if (!_contains(["server", "client", "infinite"], mode)) {
708
      throw new TypeError('`mode` must be one of "server", "client" or "infinite"');
709
    }
710
711
    options = options || {
712
      fetch: true,
713
      resetState: true
714
    };
715
716
    var state = this.state = options.resetState ?
717
      _clone(this._initState) :
718
      this._checkState(_extend({}, this.state));
719
720
    this.mode = mode;
721
722
    var self = this;
0 ignored issues
show
introduced by
Unexpected alias 'self' for 'this'.
Loading history...
723
    var fullCollection = this.fullCollection;
724
    var handlers = this._handlers = this._handlers || {},
725
      handler;
726
    if (mode != "server" && !fullCollection) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
727
      fullCollection = this._makeFullCollection(options.models || [], options);
728
      fullCollection.pageableCollection = this;
729
      this.fullCollection = fullCollection;
730
      var allHandler = this._makeCollectionEventHandler(this, fullCollection);
731
      _each(["add", "remove", "reset", "sort"], function (event) {
732
        handlers[event] = handler = _.bind(allHandler, {}, event);
733
        self.on(event, handler);
734
        fullCollection.on(event, handler);
735
      });
736
      fullCollection.comparator = this._fullComparator;
737
    } else if (mode == "server" && fullCollection) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
738
      _each(_keys(handlers), function (event) {
739
        handler = handlers[event];
740
        self.off(event, handler);
741
        fullCollection.off(event, handler);
742
      });
743
      delete this._handlers;
744
      this._fullComparator = fullCollection.comparator;
745
      delete this.fullCollection;
746
    }
747
748
    if (mode == "infinite") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
749
      var links = this.links = {};
750
      var firstPage = state.firstPage;
751
      var totalPages = ceil(state.totalRecords / state.pageSize);
752
      var lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages || firstPage;
753
      for (var i = state.firstPage; i <= lastPage; i++) {
754
        links[i] = this.url;
755
      }
756
    } else if (this.links) delete this.links;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
757
758
    if (!options.silent) this.trigger("pageable:state:change", state);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
759
760
    return options.fetch ?
761
      this.fetch(_omit(options, "fetch", "resetState")) :
762
      this;
763
  },
764
765
  /**
766
     @return {boolean} `true` if this collection can page backward, `false`
767
     otherwise.
768
  */
769
  hasPreviousPage: function () {
770
    var state = this.state;
771
    var currentPage = state.currentPage;
772
    if (this.mode != "infinite") return currentPage > state.firstPage;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
773
    return !!this.links[currentPage - 1];
774
  },
775
776
  /**
777
     @return {boolean} `true` if this collection can page forward, `false`
778
     otherwise.
779
  */
780
  hasNextPage: function () {
781
    var state = this.state;
782
    var currentPage = this.state.currentPage;
783
    if (this.mode != "infinite") return currentPage < state.lastPage;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
784
    return !!this.links[currentPage + 1];
785
  },
786
787
  /**
788
     Fetch the first page in server mode, or reset the current page of this
789
     collection to the first page in client or infinite mode.
790
791
     @param {Object} options {@linkPageableCollection#getPage} options.
792
793
     @chainable
794
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
795
     from fetch or this.
796
  */
797
  getFirstPage: function (options) {
798
    return this.getPage("first", options);
799
  },
800
801
  /**
802
     Fetch the previous page in server mode, or reset the current page of this
803
     collection to the previous page in client or infinite mode.
804
805
     @param {Object} options {@linkPageableCollection#getPage} options.
806
807
     @chainable
808
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
809
     from fetch or this.
810
  */
811
  getPreviousPage: function (options) {
812
    return this.getPage("prev", options);
813
  },
814
815
  /**
816
     Fetch the next page in server mode, or reset the current page of this
817
     collection to the next page in client mode.
818
819
     @param {Object} options {@linkPageableCollection#getPage} options.
820
821
     @chainable
822
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
823
     from fetch or this.
824
  */
825
  getNextPage: function (options) {
826
    return this.getPage("next", options);
827
  },
828
829
  /**
830
     Fetch the last page in server mode, or reset the current page of this
831
     collection to the last page in client mode.
832
833
     @param {Object} options {@linkPageableCollection#getPage} options.
834
835
     @chainable
836
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
837
     from fetch or this.
838
  */
839
  getLastPage: function (options) {
840
    return this.getPage("last", options);
841
  },
842
843
  /**
844
     Given a page index, set PageableCollection#state.currentPage to that
845
     index. If this collection is in server mode, fetch the page using the
846
     updated state, otherwise, reset the current page of this collection to
847
     the page specified by `index` in client mode. If `options.fetch` is true,
848
     a fetch can be forced in client mode before resetting the current
849
     page. Under infinite mode, if the index is less than the current page, a
850
     reset is done as in client mode. If the index is greater than the current
851
     page number, a fetch is made with the results **appended**
852
     toPageableCollection#fullCollection.  The current page will then be reset
853
     after fetching.
854
855
     @fires PageableCollection#pageable:state:change
856
857
     @param {number|string} index - The page index to go to, or the page name to
858
     look up fromPageableCollection#links in infinite mode.
859
     @param {Object} options - {@linkPageableCollection#fetch} options or
860
     [reset](http://backbonejs.org/#Collection-reset) options for client mode
861
     when `options.fetch` is `false`.
862
     @param {boolean} options.fetch = false - If true, force a
863
     {@linkPageableCollection#fetch} in client mode.
864
865
     @throws {TypeError} If `index` is not a finite integer under server or
866
     client mode, or does not yield a URL fromPageableCollection#links under
867
     infinite mode.
868
869
     @throws {RangeError} If `index` is out of bounds.
870
871
     @chainable
872
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
873
     from fetch or this.
874
  */
875
  getPage: function (index, options) {
876
877
    var mode = this.mode,
878
      fullCollection = this.fullCollection;
879
880
    options = options || {
881
      fetch: false
882
    };
883
884
    var state = this.state,
885
      firstPage = state.firstPage,
886
      currentPage = state.currentPage,
887
      lastPage = state.lastPage,
888
      pageSize = state.pageSize;
889
890
    var pageNum = index;
0 ignored issues
show
Unused Code introduced by
The assignment to variable pageNum seems to be never used. Consider removing it.
Loading history...
891
    switch (index) {
892
    case "first":
893
      pageNum = firstPage;
894
      break;
895
    case "prev":
896
      pageNum = currentPage - 1;
897
      break;
898
    case "next":
899
      pageNum = currentPage + 1;
900
      break;
901
    case "last":
902
      pageNum = lastPage;
903
      break;
904
    default:
905
      pageNum = finiteInt(index, "index");
906
    }
907
908
    this.state = this._checkState(_extend({}, state, {
909
      currentPage: pageNum
910
    }));
911
    if (!options.silent) this.trigger("pageable:state:change", this.state);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
912
913
    options.from = currentPage, options.to = pageNum;
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
introduced by
Expected an assignment or function call and instead saw an expression.
Loading history...
introduced by
Unexpected use of comma operator.
Loading history...
914
915
    var pageStart = (firstPage === 0 ? pageNum : pageNum - 1) * pageSize;
916
    var pageModels = fullCollection && fullCollection.length ?
917
      fullCollection.models.slice(pageStart, pageStart + pageSize) : [];
918
    if ((mode == "client" || (mode == "infinite" && !_isEmpty(pageModels))) &&
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
919
      !options.fetch) {
920
      this.reset(pageModels, _omit(options, "fetch"));
921
      return this;
922
    }
923
924
    if (mode == "infinite") options.url = this.links[pageNum];
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
925
926
    return this.fetch(_omit(options, "fetch"));
927
  },
928
929
  /**
930
     Fetch the page for the provided item offset in server mode, or reset the
931
     current page of this collection to the page for the provided item offset
932
     in client mode.
933
934
     @param {Object} options {@linkPageableCollection#getPage} options.
935
936
     @chainable
937
     @return {XMLHttpRequest|PageableCollection} The XMLHttpRequest
938
     from fetch or this.
939
  */
940
  getPageByOffset: function (offset, options) {
941
    if (offset < 0) {
942
      throw new RangeError("`offset must be > 0`");
943
    }
944
    offset = finiteInt(offset);
945
946
    var page = floor(offset / this.state.pageSize);
947
    if (this.state.firstPage !== 0) page++;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
948
    if (page > this.state.lastPage) page = this.state.lastPage;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
949
    return this.getPage(page, options);
950
  },
951
952
  /**
953
     Overidden to make `getPage` compatible with Zepto.
954
955
     @param {string} method
956
     @param {Backbone.Model|Backbone.Collection} model
957
     @param {Object} options
958
959
     @return {XMLHttpRequest}
960
  */
961
  sync: function (method, model, options) {
962
    var self = this;
0 ignored issues
show
introduced by
Unexpected alias 'self' for 'this'.
Loading history...
963
    if (self.mode == "infinite") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
964
      var success = options.success;
965
      var currentPage = self.state.currentPage;
966
      options.success = function (resp, status, xhr) {
967
        var links = self.links;
968
        var newLinks = self.parseLinks(resp, _extend({
969
          xhr: xhr
970
        }, options));
971
        if (newLinks.first) links[self.state.firstPage] = newLinks.first;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
972
        if (newLinks.prev) links[currentPage - 1] = newLinks.prev;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
973
        if (newLinks.next) links[currentPage + 1] = newLinks.next;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
974
        if (success) success(resp, status, xhr);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
975
      };
976
    }
977
978
    return (BBColProto.sync || Backbone.sync).call(self, method, model, options);
979
  },
980
981
  /**
982
     Parse pagination links from the server response. Only valid under
983
     infinite mode.
984
985
     Given a response body and a XMLHttpRequest object, extract pagination
986
     links from them for infinite paging.
987
988
     This default implementation parses the RFC 5988 `Link` header and extract
989
     3 links from it - `first`, `prev`, `next`. Any subclasses overriding this
990
     method __must__ return an object hash having only the keys
991
     above. However, simply returning a `next` link or an empty hash if there
992
     are no more links should be enough for most implementations.
993
994
     @param {*} resp The deserialized response body.
995
     @param {Object} options
996
     @param {XMLHttpRequest} options.xhr - The XMLHttpRequest object for this
997
     response.
998
     @return {Object}
999
  */
1000
  parseLinks: function (resp, options) {
1001
    var links = {};
1002
    var linkHeader = options.xhr.getResponseHeader("Link");
1003
    if (linkHeader) {
1004
      var relations = ["first", "prev", "next"];
1005
      _each(linkHeader.split(","), function (linkValue) {
1006
        var linkParts = linkValue.split(";");
1007
        var url = linkParts[0].replace(URL_TRIM_RE, '');
1008
        var params = linkParts.slice(1);
1009
        _each(params, function (param) {
1010
          var paramParts = param.split("=");
1011
          var key = paramParts[0].replace(PARAM_TRIM_RE, '');
1012
          var value = paramParts[1].replace(PARAM_TRIM_RE, '');
1013
          if (key == "rel" && _contains(relations, value)) links[value] = url;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1014
        });
1015
      });
1016
    }
1017
1018
    return links;
1019
  },
1020
1021
  /**
1022
     Parse server response data.
1023
1024
     This default implementation assumes the response data is in one of two
1025
     structures:
1026
1027
         [
1028
           {}, // Your new pagination state
1029
           [{}, ...] // An array of JSON objects
1030
         ]
1031
1032
     Or,
1033
1034
         [{}] // An array of JSON objects
1035
1036
     The first structure is the preferred form because the pagination states
1037
     may have been updated on the server side, sending them down again allows
1038
     this collection to update its states. If the response has a pagination
1039
     state object, it is checked for errors.
1040
1041
     The second structure is the
1042
     [Backbone.Collection#parse](http://backbonejs.org/#Collection-parse)
1043
     default.
1044
1045
     **Note:** this method has been further simplified since 1.1.7. While
1046
     existingPageableCollection#parse implementations will continue to work,
1047
     new code is encouraged to overridePageableCollection#parseState
1048
     andPageableCollection#parseRecords instead.
1049
1050
     @param {Object} resp The deserialized response data from the server.
1051
     @param {Object} the options for the ajax request
0 ignored issues
show
Documentation introduced by
The parameter the does not exist. Did you maybe forget to remove this comment?
Loading history...
1052
1053
     @return {Array.<Object>} An array of model objects
1054
  */
1055
  parse: function (resp, options) {
1056
    var newState = this.parseState(resp, _clone(this.queryParams), _clone(this.state), options);
1057
    if (newState) this.state = this._checkState(_extend({}, this.state, newState));
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1058
    return this.parseRecords(resp, options);
1059
  },
1060
1061
  /**
1062
     Parse server response for server pagination state updates. Not applicable
1063
     under infinite mode.
1064
1065
     This default implementation first checks whether the response has any
1066
     state object as documented inPageableCollection#parse. If it exists, a
1067
     state object is returned by mapping the server state keys to this
1068
     pageable collection instance's query parameter keys using `queryParams`.
1069
1070
     It is __NOT__ neccessary to return a full state object complete with all
1071
     the mappings defined inPageableCollection#queryParams. Any state object
1072
     resulted is merged with a copy of the current pageable collection state
1073
     and checked for sanity before actually updating. Most of the time, simply
1074
     providing a new `totalRecords` value is enough to trigger a full
1075
     pagination state recalculation.
1076
1077
         parseState: function (resp, queryParams, state, options) {
1078
           return {totalRecords: resp.total_entries};
1079
         }
1080
1081
     If you want to use header fields use:
1082
1083
         parseState: function (resp, queryParams, state, options) {
1084
             return {totalRecords: options.xhr.getResponseHeader("X-total")};
1085
         }
1086
1087
     This method __MUST__ return a new state object instead of directly
1088
     modifying the PageableCollection#state object. The behavior of directly
1089
     modifying PageableCollection#state is undefined.
1090
1091
     @param {Object} resp - The deserialized response data from the server.
1092
     @param {Object} queryParams - A copy of PageableCollection#queryParams.
1093
     @param {Object} state - A copy of PageableCollection#state.
1094
     @param {Object} options - The options passed through from
1095
     `parse`. (backbone >= 0.9.10 only)
1096
1097
     @return {Object} A new (partial) state object.
1098
   */
1099
  parseState: function (resp, queryParams, state, options) {
0 ignored issues
show
Unused Code introduced by
The parameter options is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1100
    if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if resp && resp.length === ....0) && _isArray(resp.1) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
1101
1102
      var newState = _clone(state);
1103
      var serverState = resp[0];
1104
1105
      _each(_pairs(_omit(queryParams, "directions")), function (kvp) {
1106
        var k = kvp[0],
1107
          v = kvp[1];
1108
        var serverVal = serverState[v];
1109
        if (!_isUndefined(serverVal) && !_.isNull(serverVal)) newState[k] = serverState[v];
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1110
      });
1111
1112
      if (serverState.order) {
1113
        newState.order = _invert(queryParams.directions)[serverState.order] * 1;
1114
      }
1115
1116
      return newState;
1117
    }
1118
  },
1119
1120
  /**
1121
     Parse server response for an array of model objects.
1122
1123
     This default implementation first checks whether the response has any
1124
     state object as documented inPageableCollection#parse. If it exists, the
1125
     array of model objects is assumed to be the second element, otherwise the
1126
     entire response is returned directly.
1127
1128
     @param {Object} resp - The deserialized response data from the server.
1129
     @param {Object} options - The options passed through from the
1130
     `parse`. (backbone >= 0.9.10 only)
1131
1132
     @return {Array.<Object>} An array of model objects
1133
   */
1134
  parseRecords: function (resp, options) {
0 ignored issues
show
Unused Code introduced by
The parameter options is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1135
    if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
1136
      return resp[1];
1137
    }
1138
1139
    return resp;
1140
  },
1141
1142
  /**
1143
     Fetch a page from the server in server mode, or all the pages in client
1144
     mode. Under infinite mode, the current page is refetched by default and
1145
     then reset.
1146
1147
     The query string is constructed by translating the current pagination
1148
     state to your server API query parameter
1149
     usingPageableCollection#queryParams. The current page will reset after
1150
     fetch.
1151
1152
     @param {Object} options - Accepts all
1153
     [Backbone.Collection#fetch](http://backbonejs.org/#Collection-fetch)
1154
     options.
1155
1156
     @return {XMLHttpRequest}
1157
  */
1158
  fetch: function (options) {
1159
1160
    options = options || {};
1161
1162
    var state = this._checkState(this.state);
1163
1164
    var mode = this.mode;
1165
1166
    if (mode == "infinite" && !options.url) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1167
      options.url = this.links[state.currentPage];
1168
    }
1169
1170
    var data = options.data || {};
1171
1172
    // dedup query params
1173
    var url = options.url || this.url || "";
1174
    if (_isFunction(url)) url = url.call(this);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1175
    var qsi = url.indexOf('?');
1176
    if (qsi != -1) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1177
      _extend(data, queryStringToParams(url.slice(qsi + 1)));
1178
      url = url.slice(0, qsi);
1179
    }
1180
1181
    options.url = url;
1182
    options.data = data;
1183
1184
    // map params except directions
1185
    var queryParams = this.mode == "client" ?
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1186
      _pick(this.queryParams, "sortKey", "order") :
1187
      _omit(_pick(this.queryParams, _keys(PageableProto.queryParams)),
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
1188
        "directions");
1189
1190
    var thisCopy = _.clone(this);
1191
    _.each(queryParams, function (v, k) {
1192
      v = _isFunction(v) ? v.call(thisCopy) : v;
1193
      if (state[k] != null && v != null && _.isUndefined(data[v])) {
0 ignored issues
show
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1194
        data[v] = state[k];
1195
      }
1196
    }, this);
1197
1198
    // fix up sorting parameters
1199
    var i;
1200
    if (state.sortKey && state.order) {
1201
      var o = _isFunction(queryParams.order) ?
1202
        queryParams.order.call(thisCopy) :
1203
        queryParams.order;
1204
      if (!_isArray(state.order)) {
1205
        data[o] = this.queryParams.directions[state.order + ""];
1206
      } else {
1207
        data[o] = [];
1208
        for (i = 0; i < state.order.length; i += 1) {
1209
          data[o].push(this.queryParams.directions[state.order[i]]);
1210
        }
1211
      }
1212
    } else if (!state.sortKey) delete data[queryParams.order];
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1213
1214
    // map extra query parameters
1215
    var extraKvps = _pairs(_omit(this.queryParams,
1216
        _keys(PageableProto.queryParams))),
0 ignored issues
show
introduced by
"PageableProto" was used before it was defined
Loading history...
1217
      kvp,
1218
      v;
1219
    for (i = 0; i < extraKvps.length; i++) {
1220
      kvp = extraKvps[i];
1221
      v = kvp[1];
1222
      v = _isFunction(v) ? v.call(thisCopy) : v;
1223
      if (v != null) data[kvp[0]] = v;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
introduced by
Use ‘===’ to compare with ‘null’.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1224
    }
1225
1226
    if (mode != "server") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison !== instead of !=.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1227
      var self = this,
0 ignored issues
show
introduced by
Unexpected alias 'self' for 'this'.
Loading history...
1228
        fullCol = this.fullCollection;
1229
      var success = options.success;
1230
      options.success = function (col, resp, opts) {
1231
1232
        // make sure the caller's intent is obeyed
1233
        opts = opts || {};
1234
        if (_isUndefined(options.silent)) delete opts.silent;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1235
        else opts.silent = options.silent;
0 ignored issues
show
introduced by
Expected { after 'else'.
Loading history...
1236
1237
        var models = col.models;
1238
        if (mode == "client") fullCol.reset(models, opts);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1239
        else {
1240
          fullCol.add(models, _extend({
1241
              at: fullCol.length
1242
            },
1243
            _extend(opts, {
1244
              parse: false
1245
            })));
1246
          self.trigger("reset", self, opts);
1247
        }
1248
1249
        if (success) success(col, resp, opts);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1250
      };
1251
1252
      // silent the first reset from backbone
1253
      return BBColProto.fetch.call(this, _extend({}, options, {
1254
        silent: true
1255
      }));
1256
    }
1257
1258
    return BBColProto.fetch.call(this, options);
1259
  },
1260
1261
  /**
1262
     Convenient method for making a `comparator` sorted by a model attribute
1263
     identified by `sortKey` and ordered by `order`.
1264
1265
     Like a Backbone.Collection, a PageableCollection will maintain the
1266
     __current page__ in sorted order on the client side if a `comparator` is
1267
     attached to it. If the collection is in client mode, you can attach a
1268
     comparator toPageableCollection#fullCollection to have all the pages
1269
     reflect the global sorting order by specifying an option `full` to
1270
     `true`. You __must__ call `sort` manually
1271
     orPageableCollection#fullCollection.sort after calling this method to
1272
     force a resort.
1273
1274
     While you can use this method to sort the current page in server mode,
1275
     the sorting order may not reflect the global sorting order due to the
1276
     additions or removals of the records on the server since the last
1277
     fetch. If you want the most updated page in a global sorting order, it is
1278
     recommended that you set PageableCollection#state.sortKey and optionally
1279
     PageableCollection#state.order, and then callPageableCollection#fetch.
1280
1281
     @protected
1282
1283
     @param {string} sortKey = this.state.sortKey - See `state.sortKey`.
1284
     @param {number} order = this.state.order - See `state.order`.
1285
     @param {(function(Backbone.Model, string): Object) | string} sortValue -
1286
     See PageableCollection#setSorting.
1287
1288
     See [Backbone.Collection.comparator](http://backbonejs.org/#Collection-comparator).
1289
  */
1290
  _makeComparator: function (sortKey, order, sortValue) {
1291
    var state = this.state;
1292
1293
    sortKey = sortKey || state.sortKey;
1294
    order = order || state.order;
1295
1296
    if (!sortKey || !order) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1297
1298
    if (!sortValue) sortValue = function (model, attr) {
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1299
      return model.get(attr);
1300
    };
1301
1302
    return function (left, right) {
1303
      var l = sortValue(left, sortKey),
1304
        r = sortValue(right, sortKey),
1305
        t;
1306
      if (order === 1) t = l, l = r, r = t;
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
introduced by
Expected an assignment or function call and instead saw an expression.
Loading history...
introduced by
Unexpected use of comma operator.
Loading history...
1307
      if (l === r) return 0;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1308
      else if (l < r) return -1;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1309
      return 1;
1310
    };
1311
  },
1312
1313
  /**
1314
     Adjusts the sorting for this pageable collection.
1315
1316
     Given a `sortKey` and an `order`, sets `state.sortKey` and
1317
     `state.order`. A comparator can be applied on the client side to sort in
1318
     the order defined if `options.side` is `"client"`. By default the
1319
     comparator is applied to thePageableCollection#fullCollection. Set
1320
     `options.full` to `false` to apply a comparator to the current page under
1321
     any mode. Setting `sortKey` to `null` removes the comparator from both
1322
     the current page and the full collection.
1323
1324
     If a `sortValue` function is given, it will be passed the `(model,
1325
     sortKey)` arguments and is used to extract a value from the model during
1326
     comparison sorts. If `sortValue` is not given, `model.get(sortKey)` is
1327
     used for sorting.
1328
1329
     @chainable
1330
1331
     @param {string} sortKey - See `state.sortKey`.
1332
     @param {number} order=this.state.order - See `state.order`.
0 ignored issues
show
Documentation Bug introduced by
The parameter order=this.state.order does not exist. Did you maybe mean order instead?
Loading history...
1333
     @param {Object} options
1334
     @param {string} options.side - By default, `"client"` if `mode` is
1335
     `"client"`, `"server"` otherwise.
1336
     @param {boolean} options.full = true
1337
     @param {(function(Backbone.Model, string): Object) | string} options.sortValue
1338
  */
1339
  setSorting: function (sortKey, order, options) {
1340
1341
    var state = this.state;
1342
1343
    state.sortKey = sortKey;
1344
    state.order = order = order || state.order;
1345
1346
    var fullCollection = this.fullCollection;
1347
1348
    var delComp = false,
1349
      delFullComp = false;
1350
1351
    if (!sortKey) delComp = delFullComp = true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1352
1353
    var mode = this.mode;
1354
    options = _extend({
1355
        side: mode == "client" ? mode : "server",
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1356
        full: true
1357
      },
1358
      options);
1359
1360
    var comparator = this._makeComparator(sortKey, order, options.sortValue);
1361
1362
    var full = options.full,
1363
      side = options.side;
1364
1365
    if (side == "client") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1366
      if (full) {
1367
        if (fullCollection) fullCollection.comparator = comparator;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1368
        delComp = true;
1369
      } else {
1370
        this.comparator = comparator;
1371
        delFullComp = true;
1372
      }
1373
    } else if (side == "server" && !full) {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
1374
      this.comparator = comparator;
1375
    }
1376
1377
    if (delComp) this.comparator = null;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1378
    if (delFullComp && fullCollection) fullCollection.comparator = null;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
1379
1380
    return this;
1381
  }
1382
1383
});
1384
1385
var PageableProto = PageableCollection.prototype;
1386
1387
if (Backbone.PageableCollection !== undefined) {
1388
  var oldPageableCollection = Backbone.PageableCollection;
1389
  /**
1390
     __BROWSER ONLY__
1391
     If you already have an object named `PageableCollection` attached to the
1392
     `Backbone` module, you can use this to return a local reference to this
1393
     PageableCollection class and reset the name PageableCollection to its
1394
     previous definition.
1395
         // The left hand side gives you a reference to this
1396
         // PageableCollection implementation, the right hand side
1397
         // resets PageableCollection to your other PageableCollection.
1398
         var PageableCollection = PageableCollection.noConflict();
1399
     @static
1400
     @return {PageableCollection}
1401
  */
1402
  Backbone.PageableCollection.noConflict = function () {
1403
    Backbone.PageableCollection = oldPageableCollection;
1404
    return PageableCollection;
1405
  };
1406
} else {
1407
  Backbone.PageableCollection = PageableCollection;
1408
}
1409
1410
export {
1411
  PageableCollection
1412
};
1413
export default PageableCollection;
1414